﻿#include "RadReadInformationMapper.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossCase.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossMeshModel.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossNodesParts.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossNodeGroup.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossElementGroup.h"
#include "FITK_Component/FITKRadiossData/FITKMaterialPlasTab.h"
#include "FITK_Component/FITKRadiossData/FITKAbstractInteraction.h"
#include "FITK_Component/FITKRadiossData/FITKInteractionTied.h"
#include "FITK_Component/FITKRadiossData/FITKAbstractRWall.h"
#include "FITK_Component/FITKRadiossData/FITKGravity.h"
#include "FITK_Component/FITKRadiossData/FITKAbstractInitialField.h"
#include "FITK_Component/FITKRadiossData/FITKAbstractBCS.h"
#include "FITK_Component/FITKRadiossData/FITKPropBeamSPR.h"
#include "FITK_Component/FITKRadiossData/FITKConnectionRBODY.h"
#include "FITK_Component/FITKRadiossData/FITKRadiossSolution.h"
#include "FITK_Component/FITKRadiossData/FITKAbstractTimeHistory.h"
#include "FITK_Interface/FITKInterfaceModel/FITKComponentManager.h"
#include "FITK_Interface/FITKInterfacePhysics/FITKAbstractSection.h"

#include <QSet>

namespace Radioss
{
    void RadReadInformationMapper::setCaseData(FITKRadiossCase* caseData)
    {
        _caseData = caseData;
    }

    void RadReadInformationMapper::map()
    {
        if (_caseData == nullptr) return;

        //part
        FITKRadiossPartManager * partManager = _caseData->getMeshModel()->getPartsManager();
        if (partManager == nullptr) return;
        const int nPart = partManager->getDataCount();
        for (int i = 0; i< nPart; ++i)
        {
            Radioss::FITKRadiossPart* part = partManager->getDataByIndex(i);
            if(part == nullptr) continue;
            const int matid = part->getMaterialID();
            const int propid = part->getPropertyID();
            //子集ID
            const int susetID = part->getSubsetID();
            part->setMaterialID(this->getMaterialID(matid));
            part->setPropertyID(this->getPropertyID(propid));
            part->setSubsetID(this->getSubsetIDByRadID(susetID));
        }
        //子集subset
        FITKRadiossSubSetManager * subsetManager = _caseData->getMeshModel()->getSubSetManager();
        if (subsetManager == nullptr) return;
        const int nSubset = subsetManager->getDataCount();
        for (int i = 0; i < nSubset; ++i)
        {
            Radioss::FITKRadiossSubSet* subset = subsetManager->getDataByIndex(i);
            if (subset == nullptr) continue;
            //嵌套子集
            if (subset->m_subsetRadIDs.size() > 1)
            {
                for (int radID: subset->m_subsetRadIDs) 
                {
                    int id = this->getSubsetIDByRadID(radID);
                    subset->appendDataObj(subsetManager->getDataByID(id));
                }
                subset->m_subsetRadIDs.clear();
                continue;
            }
            //普通子集
            int subsetID = subset->getDataObjectID();
            for (int i = 0; i < nPart; ++i)
            {
                Radioss::FITKRadiossPart* part = partManager->getDataByIndex(i);
                if (part == nullptr) continue;
                if (part->getSubsetID() == subsetID)
                {
                    subset->addPartID(part->getDataObjectID());
                }
            }
        }
        //节点集合
        FITKRadiossMeshModel* meshModel = _caseData->getMeshModel();
        if (meshModel == nullptr) return;
        Interface::FITKComponentManager* componentManager = meshModel->getComponentManager();
        if (componentManager == nullptr) return;
        const int nComponent = componentManager->getDataCount();
        for (int i = 0; i < nComponent; ++i)
        {
            Interface::FITKAbstractModelComponent* component = componentManager->getDataByIndex(i);
            FITKRadiossNodeGroup* nodesGroup = dynamic_cast<FITKRadiossNodeGroup*>(component);
            if (!nodesGroup)continue;
            FITKRadiossNodeGroupRadIOInfo* info = nodesGroup->getRadIOInfo();
            if(!info)continue;
            QString keyWords = info->getRadiossKeyWord();
            QList<int> idList{};
            if (keyWords.isEmpty())continue;
            if (keyWords == "/GRNOD/NODE") {
                for (auto id : info->getRadiossIDs()) {
                    int nodeID = getNodeIDByRadID(id);
                    if (nodeID < 1)continue;
                    idList.append(nodeID);
                }
            }
            else if (keyWords == "/GRNOD/PART")
            {
                for (auto id : info->getRadiossIDs()) {
                    FITKRadiossPart* part = getRadiossPartByFilePartID(id, false);
                    if (!part)return;
                    idList.append(part->getDataObjectID());
                }
            }
            else if (keyWords == "/GRNOD/SURF")
            {
                for (auto id : info->getRadiossIDs()) {
                    int surfID = getSurfaceSetIDByRadID(id);
                    if (surfID < 1)continue;
                    idList.append(surfID);
                }
            }
            if (idList.isEmpty())continue;
            info->setRadiossIDs(idList);
            //数据转化
            nodesGroup->transformRadIOInfo(meshModel);
        }
        //节点集合的集合
        for (int i = 0; i < nComponent; ++i)
        {
            Interface::FITKAbstractModelComponent* component = componentManager->getDataByIndex(i);
            FITKRadiossNodeGroup* nodesGroup = dynamic_cast<FITKRadiossNodeGroup*>(component);
            if (!nodesGroup)continue;
            FITKRadiossNodeGroupRadIOInfo* info = nodesGroup->getRadIOInfo();
            if (!info)continue;
            QString keyWords = info->getRadiossKeyWord();
            QSet<int> idList{};
            if (keyWords.isEmpty())continue;
            if (keyWords == "/GRNOD/GRNOD") {
                for (auto id : info->getRadiossIDs()) {
                    int grnod_ID = getNodeGroupIDByRadID(id);
                    if (grnod_ID < 1)continue;
                    Interface::FITKModelSet* set = dynamic_cast<Interface::FITKModelSet*>(componentManager->getDataByID(grnod_ID));
                    if (!set)continue;
                    idList.unite(set->getAbsoluteMember().toSet());
                }
            }
            if (idList.isEmpty())return;
            info->setRadiossKeyWord("/GRNOD/NODE");
            info->setRadiossIDs(idList.toList());
            //数据转化
            nodesGroup->transformRadIOInfo(meshModel);
        }
        //单元组
        for (int i = 0; i < nComponent; ++i)
        {
            Interface::FITKAbstractModelComponent* component = componentManager->getDataByIndex(i);
            FITKRadiossElementGroup* eleGroup = dynamic_cast<FITKRadiossElementGroup*>(component);
            if (!eleGroup)continue;
            FITKRadiossElementGroupRadIOInfo* info = eleGroup->getRadIOInfo();
            if (!info)continue;
            FITKRadiossElementGroupRadIOInfo::ElementWayType wayType = info->getElementWayType();
            FITKRadiossElementGroup::ElementGroupType groupType = eleGroup->getElementGroupType();
            QList<int> idList{};

            switch(wayType)
            {
            case FITKRadiossElementGroupRadIOInfo::ElementWayType::SameProp: 
            {
                for (auto id : info->getRadiossIDs()) {
                    int eleID = getEleIDByRadID(id);
                    if (eleID < 1)continue;
                    idList.append(eleID);
                }
                break;
            }
            case FITKRadiossElementGroupRadIOInfo::ElementWayType::PART: 
            {
                for (auto id : info->getRadiossIDs()) {
                    FITKRadiossPart* part = getRadiossPartByFilePartID(id, false);
                    if (!part)continue;
                    idList.append(part->getDataObjectID());
                }
                break;
            }
            case FITKRadiossElementGroupRadIOInfo::ElementWayType::Equal:
            {
                //to do
                break;
            }
            default:
                break;
            }
            if (idList.isEmpty())continue;
            info->setRadiossIDs(idList);
            //数据转化
            eleGroup->transformRadIOInfo(meshModel);
        }
        //初始场
        FITKInitialFieldManager*  initMgr = _caseData->getInitialFieldManager();
        if (initMgr == nullptr) return ;
        for (int i = 0; i < initMgr->getDataCount(); ++i)
        {
            Radioss::FITKAbstractInitialField* init = initMgr->getDataByIndex(i);
            if (init == nullptr) continue;
            //节点组ID
            const int grnd = init->getSetID();
            init->setSetID(this->getNodeGroupIDByRadID(grnd));
            //坐标系ID to do
        }
        //重力
        FITKGravityManager*  gMgr = _caseData->getGravityManager();
        if (gMgr == nullptr) return ;
        for (int i = 0; i < gMgr->getDataCount(); ++i)
        {
            Radioss::FITKGravity* grav = gMgr->getDataByIndex(i);
            if (grav == nullptr) continue;
            //节点组ID
            const int grnd = grav->getNodeGroupID();
            grav->setNodeGroupID(this->getNodeGroupIDByRadID(grnd));
            //坐标系ID to do
            //时间函数ID to do
            //传感器ID to do
        }
        //刚性墙
        FITKRadiossRWallManager*  wallMgr = _caseData->getRWallManager();
        if (wallMgr == nullptr) return;
        for (int i = 0; i < wallMgr->getDataCount(); ++i)
        {
            Radioss::FITKAbstractRWall* wall = wallMgr->getDataByIndex(i);
            if (wall == nullptr) continue;
            //参考节点ID
            const int ndID = wall->getNodeId();
            wall->setNodeId(this->getNodeIDByRadID(ndID));
            //节点组ID
            const int grnd1 = wall->getNodeGroupId1();
            wall->setNodeGroupId1(this->getNodeGroupIDByRadID(grnd1));
            const int grnd2 = wall->getNodeGroupId2();
            if(grnd2!=0)
                wall->setNodeGroupId2(this->getNodeGroupIDByRadID(grnd2));
        }
        //边界
        FITKRadiossBCSManager* bcMgr = _caseData->getBCSManager();
        if (bcMgr == nullptr) return ;
        for (int i = 0; i < bcMgr->getDataCount(); ++i)
        {
            Radioss::FITKAbstractBCS* bc = bcMgr->getDataByIndex(i);
            if (bc == nullptr) continue;
            //节点组ID
            const int grnd1 = bc->getGroupID1();
            const int grnd2 = bc->getGroupID2();
            bc->setGroupID(this->getNodeGroupIDByRadID(grnd1));
            if (grnd2 != 0)
                bc->setGroupID(this->getNodeGroupIDByRadID(grnd1), this->getNodeGroupIDByRadID(grnd2));
            //坐标系ID to do
        }
        //材料
        Interface::FITKMaterialManager* materialsMgr = _caseData->getMaterialManager();
        if (materialsMgr == nullptr) return ;
        for (int i = 0; i < materialsMgr->getDataCount(); ++i)
        {
            Interface::FITKAbstractMaterial* mat = materialsMgr->getDataByIndex(i);
            FITKMaterialPlasTab* material = dynamic_cast<FITKMaterialPlasTab*>(mat);
            if (!material)continue;
            //曲线ID
            FITKMaterialPlasTabData& data= material->getMaterialData();
            int id = data.m_fctIDp;
            data.m_fctIDp = this->getCurveIDByRadID(id);

            QList<int> fct_IDList{};
            for (auto id: data.m_fctID) {
                fct_IDList.append(this->getCurveIDByRadID(id));
            }
            data.m_fctID.clear();
            data.m_fctID = fct_IDList;
        }
        //相互作用
        FITKInteractionManager* interactionMgr = _caseData->getInteractionManager();
        if (interactionMgr == nullptr) return;
        for (int i = 0; i < interactionMgr->getDataCount(); ++i)
        {
            FITKAbstractInteraction* Interaction = interactionMgr->getDataByIndex(i);
            if (!Interaction)continue;
            //节点组ID
            int grnd = Interaction->getNodeGroupID();
            Interaction->setNodeGroupID(this->getNodeGroupIDByRadID(grnd));
            //面ID
            int surfID = Interaction->getMasterSurfaceID();
            Interaction->setMasterSurfaceID(this->getSurfaceSetIDByRadID(surfID));

        }
        //BeamSPR
        Interface::FITKAbstractSectionManager* sectionMgr = _caseData->getSectionManager();
        if(!sectionMgr) return;
        for (int i = 0; i < sectionMgr->getDataCount(); ++i)
        {
            FITKPropBeamSPR* beam = dynamic_cast<FITKPropBeamSPR*>(sectionMgr->getDataByIndex(i));
            if (!beam)continue;
            FITKPropValueBeamSPR* data = beam->getValue();
            if(!data)continue;

            //传感器ID  to do
            //坐标ID  to do
            //曲线ID
            //for (int i = 1; i <= 6; ++i) {
            //    ValueDOF& dof = data->getValueDOF((DOF_SPR)i);
            //    data.m_fctIDp = this->getCurveIDByRadID(id);
            //}
        }
        //刚性连接
        FITKConnectionManager* connectionMgr = _caseData->getCurrentSolution()->getConnectionManager();
        if (!connectionMgr) return;
        for (int i = 0; i < connectionMgr->getDataCount(); ++i)
        {
            FITKConnectionRBODY* connection = dynamic_cast<FITKConnectionRBODY*>(connectionMgr->getDataByIndex(i));
            if (!connection)continue;
            //点ID
            int ndID = connection->getMainNodeID();
            connection->setMainNodeID(this->getNodeIDByRadID(ndID));
            //节点组ID
            int grnd = connection->getSecondaryNodesGroupID();
            connection->setSecondaryNodesGroupID(this->getNodeGroupIDByRadID(grnd));
            //面ID
            int surfID = connection->getEnvelopeSurface();
            connection->setEnvelopeSurface(this->getSurfaceSetIDByRadID(surfID));
        }
        //时间历程
        FITKTimeHistoryManager* thMgr = _caseData->getCurrentSolution()->getTimeHietoryManager();
        if (!thMgr) return;
        for (int i = 0; i < thMgr->getDataCount(); ++i) {
            FITKAbstractTimeHistory* th = dynamic_cast<FITKAbstractTimeHistory*>(thMgr->getDataByIndex(i));
            if (!th)continue;
            FITKAbstractTimeHistory::TimeHistoryType thType = th->getTimeHistoryType();
            QList<int> objIDs{};
            if (thType == FITKAbstractTimeHistory::TimeHistory_ACCEL) {
                for (int radID : th->getObjIDs())
                    objIDs.append(this->getProbeIDByRadID(radID));
            }
            else if (thType == FITKAbstractTimeHistory::TimeHistory_INTER) {
                for (int radID : th->getObjIDs())
                    objIDs.append(this->getInteractionIDByRadID(radID));
            }
            else if (thType == FITKAbstractTimeHistory::TimeHistory_RWALL) {
                for (int radID : th->getObjIDs())
                    objIDs.append(this->getRWallIDByRadID(radID));
            }
            else if (thType == FITKAbstractTimeHistory::TimeHistory_RBODY) {
                for (int radID : th->getObjIDs())
                    objIDs.append(this->getConnectionIDByRadID(radID));
            }
            else if (thType == FITKAbstractTimeHistory::TimeHistory_SECTIO) {
                //无/SECT  to do
            }
            if(objIDs.isEmpty())continue;
            th->setObjIDs(objIDs);
        }
    }

    FITKRadiossPart * RadReadInformationMapper::getRadiossPartByFilePartID(int id, bool isCreate)
    {
        if(_caseData == nullptr) return nullptr;

        //获取part管理器
        FITKRadiossPartManager * partManager = _caseData->getMeshModel()->getPartsManager();
        if(partManager == nullptr) return nullptr;  
        
        if(_partIDMap.contains(id))
        {
            //如果partIDMap中存在该id，直接返回对应的part
            int partID = _partIDMap.value(id);
            return partManager->getDataByID(partID);
        }
        else
        {
            if(!isCreate)return nullptr;
            //如果不存在，返回创建 part
            FITKRadiossPart* part = new FITKRadiossPart();
            partManager->appendDataObj(part);
            _partIDMap.insert(id, part->getDataObjectID());
            return part;
        }
    }

    void RadReadInformationMapper::insertMaterialIDMap(const int radID, const int materialID)
    {
        _materialIDMap.insert(radID, materialID);
    }

    int RadReadInformationMapper::getMaterialID(const int radID)
    {
        return _materialIDMap.contains(radID) ? _materialIDMap.value(radID) : 0;
    }

    void RadReadInformationMapper::insertPropertyIDMap(const int radID, const int propertyID)
    {
        _propertyIDMap.insert(radID, propertyID);
    }

    int RadReadInformationMapper::getPropertyID(const int radID)
    {
        return _propertyIDMap.contains(radID) ? _propertyIDMap.value(radID) : 0;
    }

    void RadReadInformationMapper::insertNodeGroupIDMap(const int radID, const int nodeGroupID)
    {
        _nodeGroupIDMap.insert(radID, nodeGroupID);
    }
    int RadReadInformationMapper::getNodeGroupIDByRadID(int radID) const
    {
        return _nodeGroupIDMap.contains(radID) ? _nodeGroupIDMap.value(radID) : 0;
    }


    void RadReadInformationMapper::insertNodeIDMap(const int radID, const int nodeID)
    {
        _nodeIDMap.insert(radID, nodeID);
    }
    int RadReadInformationMapper::getNodeIDByRadID(int radID) const
    {
        return _nodeIDMap.contains(radID) ? _nodeIDMap.value(radID) : 0;
    }

    void RadReadInformationMapper::insertEleIDMap(const int radID, const int eleID)
    {
        _eleIDMap.insert(radID, eleID);
    }
    int RadReadInformationMapper::getEleIDByRadID(int eleID) const
    {
        return _eleIDMap.contains(eleID) ? _eleIDMap.value(eleID) : 0;
    }

    void RadReadInformationMapper::insertSubsetIDMap(const int radID, const int subsetID)
    {
        _subsetIDMap.insert(radID, subsetID);
    }
    int RadReadInformationMapper::getSubsetIDByRadID(int subsetID) const
    {
        return _subsetIDMap.contains(subsetID) ? _subsetIDMap.value(subsetID) : 0;
    }

    void RadReadInformationMapper::insertCurveIDMap(const int radID, const int curveID)
    {
        _curveIDMap.insert(radID, curveID);
    }
    int RadReadInformationMapper::getCurveIDByRadID(int curveID) const
    {
        return _curveIDMap.contains(curveID) ? _curveIDMap.value(curveID) : 0;
    }

    void RadReadInformationMapper::insertSurfaceSetIDMap(const int radID, const int surfaceID)
    {
        _surfaceIDMap.insert(radID, surfaceID);
    }
    int RadReadInformationMapper::getSurfaceSetIDByRadID(int surfaceID) const
    {
        return _surfaceIDMap.contains(surfaceID) ? _surfaceIDMap.value(surfaceID) : 0;
    }

    void RadReadInformationMapper::insertInteractionIDMap(const int radID, const int interactionID)
    {
        _interactionIDMap.insert(radID, interactionID);
    }
    int RadReadInformationMapper::getInteractionIDByRadID(int interactionID) const
    {
        return _interactionIDMap.contains(interactionID) ? _interactionIDMap.value(interactionID) : 0;
    }


    void RadReadInformationMapper::insertConnectionIDMap(const int radID, const int connectionID)
    {
        _connectionIDMap.insert(radID, connectionID);
    }

    int RadReadInformationMapper::getConnectionIDByRadID(int connectionID) const
    {
        return _connectionIDMap.contains(connectionID) ? _connectionIDMap.value(connectionID) : 0;
    }

    void RadReadInformationMapper::insertElementGroupIDMap(const int radID, const int elementGroupID)
    {
        _elementGroupID.insert(radID, elementGroupID);
    }
    int RadReadInformationMapper::getElementGroupIDByRadID(int elementGroupID) const
    {
        return _elementGroupID.contains(elementGroupID) ? _elementGroupID.value(elementGroupID) : 0;
    }

    void RadReadInformationMapper::insertProbeIDMap(const int radID, const int probeID)
    {
        _probeID.insert(radID, probeID);
    }
    int RadReadInformationMapper::getProbeIDByRadID(int probeID) const
    {
        return _probeID.contains(probeID) ? _probeID.value(probeID) : 0;
    }

    void RadReadInformationMapper::insertRWallIDMap(const int radID, const int rwallID)
    {
        _rWallID.insert(radID, rwallID);
    }
    int RadReadInformationMapper::getRWallIDByRadID(int rwallID) const
    {
        return _rWallID.contains(rwallID) ? _rWallID.value(rwallID) : 0;

    }
}
